package com.wande.dataplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wande.common.core.exception.ServiceException;
import com.wande.common.core.utils.StringUtils;
import com.wande.common.mybatis.core.page.PageQuery;
import com.wande.common.mybatis.core.page.TableDataInfo;
import com.wande.common.satoken.utils.LoginHelper;
import com.wande.dataplatform.domain.*;
import com.wande.dataplatform.domain.bo.ProjectBo;
import com.wande.dataplatform.domain.bo.ProjectMemberBo;
import com.wande.dataplatform.domain.dto.ProjectResourceStatisticsDTO;
import com.wande.dataplatform.domain.vo.ProjectMemberVO;
import com.wande.dataplatform.domain.vo.ProjectVO;
import com.wande.dataplatform.mapper.*;
import com.wande.dataplatform.service.IProjectService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 项目服务实现
 *
 * @author wande
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectServiceImpl implements IProjectService {

    private final ProjectMapper projectMapper;
    private final ProjectMemberMapper projectMemberMapper;
    private final DataSourceMapper dataSourceMapper;
    private final DataModelMapper dataModelMapper;
    private final EtlTaskMapper etlTaskMapper;

    @Override
    public TableDataInfo<ProjectVO> queryPageList(ProjectBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<Project> wrapper = buildQueryWrapper(bo);
        Page<ProjectVO> page = projectMapper.selectVoPage(pageQuery.build(), wrapper);
        
        // 填充成员数量
        page.getRecords().forEach(vo -> {
            Long memberCount = projectMemberMapper.selectCount(
                Wrappers.lambdaQuery(ProjectMember.class)
                    .eq(ProjectMember::getProjectId, vo.getId())
            );
            vo.setMemberCount(memberCount.intValue());
        });
        
        return TableDataInfo.build(page);
    }

    @Override
    public List<ProjectVO> queryList(ProjectBo bo) {
        LambdaQueryWrapper<Project> wrapper = buildQueryWrapper(bo);
        return projectMapper.selectVoList(wrapper);
    }

    @Override
    public ProjectVO queryById(Long id) {
        ProjectVO vo = projectMapper.selectVoById(id);
        if (vo == null) {
            throw new ServiceException("项目不存在");
        }
        
        // 填充资源统计
        ProjectResourceStatisticsDTO statistics = getResourceStatistics(id);
        vo.setMemberCount(statistics.getMemberCount());
        vo.setDatasourceCount(statistics.getDatasourceCount());
        vo.setModelCount(statistics.getModelCount());
        vo.setEtlTaskCount(statistics.getEtlTaskCount());
        
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProject(ProjectBo bo) {
        // 检查项目编码是否重复
        String tenantIdStr = LoginHelper.getTenantId();
        Long tenantId = StringUtils.isNotBlank(tenantIdStr) ? Long.parseLong(tenantIdStr) : null;
        Long count = projectMapper.selectCount(
            Wrappers.lambdaQuery(Project.class)
                .eq(Project::getTenantId, tenantId)
                .eq(Project::getCode, bo.getCode())
        );
        if (count > 0) {
            throw new ServiceException("项目编码已存在");
        }
        
        Project project = BeanUtil.toBean(bo, Project.class);
        project.setTenantId(tenantId);
        project.setStatus(1); // 默认正常状态
        projectMapper.insert(project);
        
        // 自动添加创建人为项目负责人
        ProjectMember member = new ProjectMember();
        member.setProjectId(project.getId());
        member.setUserId(bo.getOwnerId());
        member.setUserName(bo.getOwnerName());
        member.setRole("OWNER");
        member.setJoinTime(LocalDateTime.now());
        projectMemberMapper.insert(member);
        
        return project.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateProject(ProjectBo bo) {
        Project project = projectMapper.selectById(bo.getId());
        if (project == null) {
            throw new ServiceException("项目不存在");
        }
        
        // 检查项目编码是否重复
        if (!project.getCode().equals(bo.getCode())) {
            Long count = projectMapper.selectCount(
                Wrappers.lambdaQuery(Project.class)
                    .eq(Project::getTenantId, project.getTenantId())
                    .eq(Project::getCode, bo.getCode())
                    .ne(Project::getId, bo.getId())
            );
            if (count > 0) {
                throw new ServiceException("项目编码已存在");
            }
        }
        
        BeanUtil.copyProperties(bo, project, "id", "tenantId", "createBy", "createTime");
        return projectMapper.updateById(project) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteProject(Long id) {
        Project project = projectMapper.selectById(id);
        if (project == null) {
            throw new ServiceException("项目不存在");
        }
        
        // 检查是否有关联资源
        ProjectResourceStatisticsDTO statistics = getResourceStatistics(id);
        if (statistics.getDatasourceCount() > 0 || statistics.getModelCount() > 0 
            || statistics.getEtlTaskCount() > 0) {
            throw new ServiceException("项目下存在关联资源，无法删除");
        }
        
        // 删除项目成员
        projectMemberMapper.delete(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, id)
        );
        
        // 删除项目
        return projectMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean archiveProject(Long id) {
        Project project = projectMapper.selectById(id);
        if (project == null) {
            throw new ServiceException("项目不存在");
        }
        
        project.setStatus(0);
        return projectMapper.updateById(project) > 0;
    }

    @Override
    public Boolean restoreProject(Long id) {
        Project project = projectMapper.selectById(id);
        if (project == null) {
            throw new ServiceException("项目不存在");
        }
        
        project.setStatus(1);
        return projectMapper.updateById(project) > 0;
    }

    @Override
    public List<ProjectMemberVO> queryMemberList(Long projectId) {
        return projectMemberMapper.selectVoList(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, projectId)
                .orderByAsc(ProjectMember::getJoinTime)
        );
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addMember(ProjectMemberBo bo) {
        // 检查是否已是成员
        Long count = projectMemberMapper.selectCount(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, bo.getProjectId())
                .eq(ProjectMember::getUserId, bo.getUserId())
        );
        if (count > 0) {
            throw new ServiceException("用户已是项目成员");
        }
        
        ProjectMember member = BeanUtil.toBean(bo, ProjectMember.class);
        member.setJoinTime(LocalDateTime.now());
        return projectMemberMapper.insert(member) > 0;
    }

    @Override
    public Boolean updateMember(ProjectMemberBo bo) {
        ProjectMember member = projectMemberMapper.selectById(bo.getId());
        if (member == null) {
            throw new ServiceException("成员不存在");
        }
        
        member.setRole(bo.getRole());
        return projectMemberMapper.updateById(member) > 0;
    }

    @Override
    public Boolean deleteMember(Long id) {
        ProjectMember member = projectMemberMapper.selectById(id);
        if (member == null) {
            throw new ServiceException("成员不存在");
        }
        
        // 检查是否为负责人
        if ("OWNER".equals(member.getRole())) {
            throw new ServiceException("无法删除项目负责人");
        }
        
        return projectMemberMapper.deleteById(id) > 0;
    }

    @Override
    public Boolean isMember(Long projectId, Long userId) {
        Long count = projectMemberMapper.selectCount(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, projectId)
                .eq(ProjectMember::getUserId, userId)
        );
        return count > 0;
    }

    @Override
    public Boolean hasPermission(Long projectId, Long userId, String requiredRole) {
        ProjectMember member = projectMemberMapper.selectOne(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, projectId)
                .eq(ProjectMember::getUserId, userId)
        );
        
        if (member == null) {
            return false;
        }
        
        // 角色权限层级: OWNER > ADMIN > DEVELOPER > VIEWER
        String[] roles = {"VIEWER", "DEVELOPER", "ADMIN", "OWNER"};
        int memberRoleLevel = getRoleLevel(member.getRole(), roles);
        int requiredRoleLevel = getRoleLevel(requiredRole, roles);
        
        return memberRoleLevel >= requiredRoleLevel;
    }

    @Override
    public ProjectResourceStatisticsDTO getResourceStatistics(Long projectId) {
        ProjectResourceStatisticsDTO dto = new ProjectResourceStatisticsDTO();
        dto.setProjectId(projectId);
        
        Project project = projectMapper.selectById(projectId);
        if (project != null) {
            dto.setProjectName(project.getName());
        }
        
        // 统计成员数量
        Long memberCount = projectMemberMapper.selectCount(
            Wrappers.lambdaQuery(ProjectMember.class)
                .eq(ProjectMember::getProjectId, projectId)
        );
        dto.setMemberCount(memberCount.intValue());
        
        // 统计数据源数量
        Long datasourceCount = dataSourceMapper.selectCount(
            Wrappers.lambdaQuery(DataSource.class)
                .eq(DataSource::getProjectId, projectId)
        );
        dto.setDatasourceCount(datasourceCount.intValue());
        
        // 统计数据模型数量
        Long modelCount = dataModelMapper.selectCount(
            Wrappers.lambdaQuery(DataModel.class)
                .eq(DataModel::getProjectId, projectId)
        );
        dto.setModelCount(modelCount.intValue());
        
        // 统计ETL任务数量
        Long etlTaskCount = etlTaskMapper.selectCount(
            Wrappers.lambdaQuery(EtlTask.class)
                .eq(EtlTask::getProjectId, projectId)
        );
        dto.setEtlTaskCount(etlTaskCount.intValue());
        
        return dto;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<Project> buildQueryWrapper(ProjectBo bo) {
        LambdaQueryWrapper<Project> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Project::getTenantId, LoginHelper.getTenantId());
        wrapper.like(ObjectUtil.isNotEmpty(bo.getName()), Project::getName, bo.getName());
        wrapper.eq(ObjectUtil.isNotEmpty(bo.getCode()), Project::getCode, bo.getCode());
        wrapper.eq(ObjectUtil.isNotEmpty(bo.getStatus()), Project::getStatus, bo.getStatus());
        wrapper.eq(ObjectUtil.isNotEmpty(bo.getOwnerId()), Project::getOwnerId, bo.getOwnerId());
        wrapper.orderByDesc(Project::getCreateTime);
        return wrapper;
    }

    /**
     * 获取角色级别
     */
    private int getRoleLevel(String role, String[] roles) {
        for (int i = 0; i < roles.length; i++) {
            if (roles[i].equals(role)) {
                return i;
            }
        }
        return -1;
    }
}
